package missObjects;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.logging.Logger;

import db.RawData;
import main.Prop;

/**
 * Handle Block writing in file and DB and reading form DB. Onvly methods
 * differs from RofMissionObject
 * 
 * @author lefuneste
 *
 */
public class RofMissObjBlock extends RofMissionObject {

	private static int writeInDBCount = 0;
	private static Logger LOGGER = Logger.getLogger("RofLogger");

	static {
		LOGGER.getUseParentHandlers();
	}

	// initFlag to init TABLE if not exists when writing the first Block into DB

	/**
	 * Create a empty block object
	 */
	public RofMissObjBlock() {
		super();
		this.objectType = "Block";
	}

	/**
	 * Create a block from a template object previously read in a file
	 * 
	 * @param template
	 *            : object read in file
	 */
	public RofMissObjBlock(RofTemplateObject template) {
		super();
		// common part
		this.objectType = template.objectType;
		this.indexInfile = template.indexInfile;
		this.mapID = template.mapID;
		this.fileID = template.fileID;
		this.name = template.name;
		this.groupID = template.groupID;
		// standard part
		this.Xpos = template.Xpos;
		this.Ypos = template.Ypos;
		this.Zpos = template.Zpos;
		this.Xori = template.Xori;
		this.Yori = template.Yori;
		this.Zori = template.Zori;
		this.model = template.model;
		// specific fields
		for (RawData data : template.unProcessedData) {
			this.unProcessedData.add(data);
		}

	}

	/**
	 * Store the Block into DB
	 * 
	 * @param con
	 *            connection to DB
	 * @throws SQLException
	 */
	public void storeToDB(Connection con) throws SQLException {
		try (Statement stmt = con.createStatement()) {

			String sql = "INSERT OR IGNORE INTO "
					+ Prop.get("BLOCK")
					+ " (name, objectType, fileID, groupID, indexInFile, fileID, mapID, Xpos, Ypos, Zpos, Xori, Yori, Zori, model ) VALUES('"
					+ this.name + "','" + this.objectType + "','" + this.fileID + "','" + this.groupID
					+ "','" + this.indexInfile + "','" + this.fileID + "','"
					+ this.mapID + "','" + this.Xpos + "','" + this.Ypos
					+ "','" + this.Zpos + "','" + this.Xori + "','" + this.Yori
					+ "','" + this.Zori + "','" + this.model + "');";
			stmt.executeUpdate(sql);
			writeInDBCount++;

			// storage of associated non processed data

			for (int i = 0; i < unProcessedData.size(); i++) {
				sql = "INSERT OR IGNORE INTO " + Prop.get("RAWDATA")
						+ " (id, objID, fileID, RawData ) VALUES('"
						+ this.unProcessedData.get(i).getOrderNum()+"','" +this.indexInfile + "','" + this.fileID + "','"
						+ this.unProcessedData.get(i).getLine() + "');";
				stmt.executeUpdate(sql);
			}

			LOGGER.fine("Block " + this.name + "written into DB, "
					+ unProcessedData.size()
					+ " associated lines added into RawData");
			stmt.close();

		} catch (Exception e) {
			LOGGER.severe(e.getClass().getName() + ": " + e.getMessage());
			throw (e);
		}

	}

	/**
	 * Retrieve a Block object from the database by using its IndexInFile and
	 * fileID
	 * 
	 * @param con
	 *            : connection to DB
	 * @param IndexInFile
	 *            : ref#1 of Block
	 * @param fileID
	 *            : ref#2 of Block
	 * @return
	 * @throws SQLException
	 */
	public void readFromDB(Connection con, int indexInFile, int fileID)
			throws SQLException {

		ResultSet results1 = null;
		ResultSet results2 = null;

		try (Statement stmt = con.createStatement()) {
			String sql = "SELECT * from " + Prop.get("BLOCK")
					+ " WHERE fileID=" + fileID + " AND IndexInFile="
					+ indexInFile + " ;";

			results1 = stmt.executeQuery(sql);

			Statement stmt2 = con.createStatement();
			sql = "SELECT * from " + Prop.get("RAWDATA") + " WHERE fileID="
					+ fileID + " AND objID=" + indexInFile + " ORDER BY id;";
			results2 = stmt2.executeQuery(sql);

			this.readfromResultSet(results1, results2);

		} catch (Exception e) {
			LOGGER.severe(e.getClass().getName() + ": " + e.getMessage());
			throw (e);
		}
	}

	/**
	 * Retrieve a Block object from records in DB
	 * 
	 * @param reqResultsblock
	 *            results of a DB request for the block
	 * @param reqResulsraw
	 *            results of a DB request for the associated raw data
	 * @throws SQLException
	 */
	public void readfromResultSet(ResultSet reqResultsblock,
			ResultSet reqResulsraw) throws SQLException {
		RawData rawLine=null;
		try {
			// block info retrieval
			while (reqResultsblock.next()) {
				// should only be one, in other case only the last will be
				// returned
				this.objectType = reqResultsblock.getString("objectType");
				this.indexInfile = reqResultsblock.getInt("indexInFile");
				this.mapID = reqResultsblock.getString("mapID");
				this.fileID = reqResultsblock.getInt("fileID");
				this.name = reqResultsblock.getString("name");
				this.groupID = reqResultsblock.getInt("groupID");
				this.Xpos = reqResultsblock.getDouble("Xpos");
				this.Ypos = reqResultsblock.getDouble("Ypos");
				this.Zpos = reqResultsblock.getDouble("Zpos");
				this.Xori = reqResultsblock.getDouble("Xori");
				this.Yori = reqResultsblock.getDouble("Yori");
				this.Zori = reqResultsblock.getDouble("Zori");
				this.model = reqResultsblock.getString("model");
			}
			// raw data info retrieval
			while (reqResulsraw.next()) {
				String line=reqResulsraw.getString("RawData");
				int rawDataIndex = reqResulsraw.getInt("id");
				rawLine = new RawData(rawDataIndex, line);
				this.unProcessedData.add(rawLine);
			}
		} catch (Exception e) {
			LOGGER.severe(e.getClass().getName() + ": " + e.getMessage());
			throw (e);
		}
	}

	public String toString() {
		String results = "";
		results = this.name + ";" + this.indexInfile + ";" + this.fileID + ";"
				+ this.mapID;
		return results;
	}

}
